﻿using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using UCL.Powersource.Analysis;

namespace UCL.Powersource.Statistics
{
    /// <summary>
    /// This statistic retrieves the number of valid tests for Backlog items
    /// that are in a 'Done' state. A test is valid if it is in 'Ready' state
    /// for Test cases or 'Done' for Tasks that test a backlog.
    /// </summary>
    [Export(typeof(IStatistic))]
    [DataContract(IsReference = true)]
    public class DonePBITestsNumb : LinksRelatedWIStatisticsBase
    {
        [ExcludeFromCodeCoverage]
        public override string Label
        {
            get { return "PBI Done Tests Number"; }
        }

        [ExcludeFromCodeCoverage]
        public override string Description
        {
            get { return "Number of tests for Product Backlog Items in Done state in an iteration"; }
        }

        [ExcludeFromCodeCoverage]
        public override string Name
        {
            get { return "DonePBITestsNumb"; }
        }

        public static readonly Guid CN_Statistic_Guid = new Guid("2DD505B5-E306-4A2C-86B1-CAF0F7588D4E");
         [ExcludeFromCodeCoverage]
        public override Guid Statistic_Guid
        {
            get { return CN_Statistic_Guid; }
        }

        
        private string DonePBITestedByDoneTasks { get { return _DonePBITestedByDoneTasks; } }

        
        private string DonePBIWithTestsCasesTree { get { return _DonePBIWithTestsCasesTree; } }

        /// <summary>
        /// Class for invalid work items calculation
        /// </summary>
        /// <param name="collUri">Tfs stat project collection Uri</param>
        /// <param name="iteration">Work item iteration</param>
        /// <param name="finishDate">Finish date</param>
        /// <param name="wiStore">Work item store</param>
        /// <returns>Number of invalid work items</returns>
        protected override int? CountInvalidWI(string collUri, string iteration, DateTime finishDate, WorkItemStore wiStore)
        {
            if (!linksCollectionCache.ContainsKey(collUri))
            {
                linksCollectionCache.Add(collUri, new Dictionary<string, Dictionary<string, Dictionary<DateTime, WorkItemLinkInfo[]>>>());
                linksCollectionCache[collUri].Add(iteration, new Dictionary<string, Dictionary<DateTime, WorkItemLinkInfo[]>>());
                linksCollectionCache[collUri][iteration].Add("DonePBITestedByDoneTasks", new Dictionary<DateTime, WorkItemLinkInfo[]>());
                linksCollectionCache[collUri][iteration].Add("DonePBIWithTestsCasesTree", new Dictionary<DateTime, WorkItemLinkInfo[]>());
            }
            else if (!linksCollectionCache[collUri].ContainsKey(iteration))
            {
                linksCollectionCache[collUri].Add(iteration, new Dictionary<string, Dictionary<DateTime, WorkItemLinkInfo[]>>());
                linksCollectionCache[collUri][iteration].Add("DonePBITestedByDoneTasks", new Dictionary<DateTime, WorkItemLinkInfo[]>());
                linksCollectionCache[collUri][iteration].Add("DonePBIWithTestsCasesTree", new Dictionary<DateTime, WorkItemLinkInfo[]>());
            }

            List<int> wiList = new List<int>();

            queryLinkResults = GetQueryLinkResults(DonePBITestedByDoneTasks, collUri, finishDate, iteration, wiStore, "DonePBITestedByDoneTasks");
            wiList.AddRange(GetListOfIds(true, true, wiStore, iteration));

            queryLinkResults = GetQueryLinkResults(DonePBIWithTestsCasesTree, collUri, finishDate, iteration, wiStore, "DonePBIWithTestsCasesTree");
            wiList.AddRange(GetListOfIds(true, true, wiStore, iteration));

            return wiList.Select(p => p).Distinct().Count();
        }

        /// <summary>
        /// Product backlog items with the "Done" state which are tested by the Done tasks
        /// </summary>
        [DataMember]
        private string _DonePBITestedByDoneTasks =
                "SELECT [Id] " +
                "FROM WorkItemLinks " +
                "WHERE ([Source].[System.WorkItemType] = 'Product Backlog Item'  " +
                "AND  [Source].[State] = 'Done' )" +
                "AND  ([System.Links.LinkType] = 'Microsoft.VSTS.Common.TestedBy-Forward') " +
                "AND ([Target].[System.WorkItemType] = 'Task' " +
                "AND [Target].[State] = 'Done') " +
                "mode(MustContain) AsOf @AsOf";

        /// <summary>
        /// Product Backlog items with the test cases tree
        /// </summary>
        [DataMember]
        private string _DonePBIWithTestsCasesTree =
                "SELECT [Id] " +
                "FROM WorkItemLinks " +
                "WHERE ([Source].[System.WorkItemType] = 'Product Backlog Item'  " +
                "AND  [Source].[State] = 'Done') " +
                "And ([System.Links.LinkType] = 'System.LinkTypes.Hierarchy-Forward') " +
                "And ([Target].[System.WorkItemType] = 'Test Case'  " +
                "AND  [Target].[State] = 'Ready') " +
                "mode(Recursive)";
        

    }
}
